home *** CD-ROM | disk | FTP | other *** search
/ Internet Info 1994 March / Internet Info CD-ROM (Walnut Creek) (March 1994).iso / networking / info-service / gopher / Unix / gateways / gopher2FTP / g2fd.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-04-08  |  8.6 KB  |  367 lines

  1. /* -------------------------------------------------
  2. *    g2fd.c          Gopher to FTP gateway daemon.
  3. *    Version 0.3 Hacked up: April 1992.  Farhad Anklesaria.
  4. *    Based on a Perl story by John Ladwig.
  5. *    Based on a Perl story by Farhad Anklesaria.
  6. *
  7. *    To be run by inetd.
  8. *    For installation, read the companion README.... or
  9. *    if you don't feel like doing that, the brief instructions
  10. *    are below:
  11. *    
  12. *    First edit the local parameters in defines below.
  13. *    Then do a "make g2fd"
  14. *    Then place the binary (g2fd) in some reasonable place,
  15. *        eg in /usr/local/bin
  16. *    Finally, edit /etc/services and /etc/servers or
  17. *         /etc/inetd.conf as the case may be.  Kill
  18. *        and restart inetd.
  19. *
  20. *    This file looks best with tabstops set to 4 rather than 8.
  21. ---------------------------------------------------- */
  22.  
  23. #include <stdio.h>
  24. #include <string.h>
  25. #include <sys/types.h>
  26. #include <signal.h>
  27. /*==============Local parameters to be edited in===============*/
  28. #define    LOCALHOST    "hell.micro.umn.edu"    /* This host's domain name */
  29. #define    LOCALPORT    70                    /* This daemon's port */
  30. #define MAXLOAD        8.0                        /* For load limit if > 1 */ 
  31. #define    FTP            "/usr/ucb/ftp"            /* To invoke ftp */
  32. #define    UPTIME        "/usr/ucb/uptime"        /* To check loadavg.  Ick. */
  33. #define    LIST        "/tmp/gftpL+"            /* Temp list file prefix */
  34. #define    DATA        "/tmp/gftpD+"            /* Temp data file prefix */
  35. /*=============================================================*/
  36.  
  37. #define GFILE    0        /* Gopher item types */
  38. #define GDIR    1
  39. #define GBINHEX    4
  40. #define GDOSB    5
  41. #define GUNIXB    9
  42.  
  43. #define SLEN    255        /* Generic small buffer length */
  44. #define    TMOUT    1200    /* 20 minutes is plenty long enough */
  45.  
  46. char    *appname;
  47. char    ftp[SLEN] = FTP;
  48. char    myName[SLEN] = LOCALHOST;
  49. char    tmpList[SLEN] = LIST;
  50. char    tmpData[SLEN] = DATA;
  51. char    query[BUFSIZ];                /* input redirected by inetd */
  52. char     *host, *thing;                /* pointers into query */
  53. int        gettingFile = 1;
  54. int        gettingBinary = 0;
  55. int        childpid;
  56.  
  57. main(argc, argv)
  58.     int argc;
  59.     char * argv[];
  60.  
  61. {
  62.     char buf[BUFSIZ];
  63.     int pid, Cleanup();
  64.     
  65.  
  66.     appname = argv[0];
  67.     GenerateUniqueFiles(tmpList, tmpData);
  68.     
  69.     if ((childpid = fork()) == -1) {
  70.         Abort("Can't fork.");
  71.     } else if (childpid != 0) {   /* We are the parent and we wait*/
  72.         WaitForChild();
  73.     }
  74.     
  75.     /* If we get here we are the child and we can do some work */
  76.     signal(SIGPIPE, Cleanup);  /* This and the extra fork is paranoia */
  77.     if (LoadTooHigh()) 
  78.             Abort("Too many connections.  Try again later.");
  79.     gets(query);                    /* Courtesy of inetd */
  80.     
  81.     SendQuery(query);
  82.     TranslateResults();
  83.     Cleanup();
  84.     exit(0);
  85.  
  86. }
  87.  
  88. /*--------------------------------*/
  89.  
  90. WaitForChild()
  91. {
  92.     int status, RoundEmUp();
  93.     
  94.     signal(SIGALRM, RoundEmUp);
  95.     alarm(TMOUT);
  96.     wait(&status);
  97.     exit(status);
  98. }
  99.  
  100. /*--------------------------------*/
  101. LoadTooHigh()
  102. {
  103.     char stuff[SLEN];   float load; char *t;
  104.     FILE *fd, *popen();
  105.  
  106.     if (MAXLOAD <= 1.0) return(0);
  107.  
  108.     if (((fd = popen(UPTIME, "r")) == NULL) || 
  109.         (fgets(stuff, sizeof stuff, fd) == NULL))
  110.             Abort("Can't determinine load average.");
  111.     pclose(fd);
  112.     t = strtok(stuff, " \t");
  113.     while ((t != NULL) && (strcasecmp(t, "average:") != 0)) {
  114.         t = strtok(NULL, " \t");
  115.     }
  116.     if (t == NULL) Abort("Can't determinine load average.");
  117.     t = strtok(NULL, " \t");
  118.     sscanf(t, "%f", &load);
  119.     return(load > MAXLOAD);
  120. }
  121.  
  122. /*--------------------------------*/
  123.  
  124. SendQuery(query)
  125.     char *query;
  126.  
  127. {
  128.     int sLen, termCh;
  129.     char *at;
  130.     FILE *fd, *popen();
  131.  
  132.     /*  printf("The full query was %s\n", query);  Debug  */
  133.     
  134.     if ((sLen = strlen(query)) <= 2) Abort("No host name specified.");
  135.     query[--sLen] = '\0';            /* Knock off the CR: host@path/<cr>*/
  136.     host = query;
  137.     at = strchr(query, '@');
  138.     if (at == NULL) Abort("Not a valid ftp query.");
  139.     thing = at + 1;
  140.     *at = '\0';             /*Sneakily chop it into two strings*/
  141.     sprintf(ftp + strlen(ftp), " -n %s > %s", host, tmpList);
  142.     if ((fd = popen(ftp, "w")) == NULL) Abort("Can't run ftp.");
  143.     FailErr(fprintf(fd, "user anonymous gopher@%s\n", LOCALHOST));
  144.     
  145.     sLen = strlen(thing);
  146.     termCh = thing[sLen - 1];            /* Grab possible end char: / etc */
  147.     if ((termCh == '*') || (termCh == '@'))    /*  || (termCh == '/')  */
  148.         thing[sLen - 1] = '\0';
  149.     /* printf("At this point host: %s   thing: %s\n", host, thing);    */
  150.     if (termCh == '/') {    /* We have a directory */
  151.         gettingFile = 0;
  152.         if (strlen(thing) > 0) FailErr(fprintf(fd, "cd \"%s\"\n", thing));
  153.         FailErr(fprintf(fd, "ls -F\n"));
  154.     } else {                /* We have a file */
  155.         gettingFile = 1;
  156.         if (gettingBinary = IsBinaryType(thing))  
  157.                 FailErr(fprintf(fd, "binary\n"));
  158.         FailErr(fprintf(fd, "get \"%s\" \"%s\"\n", thing, tmpData));
  159.     }
  160.     FailErr(fprintf(fd, "quit\n"));
  161.     pclose(fd);
  162.     
  163.  
  164. }
  165.  
  166. /*--------------------------------*/
  167.  
  168. TranslateResults()
  169. {
  170.     FILE *fp, *OpenOrDie();
  171.     char buf[BUFSIZ], theName[SLEN];
  172.     int fd, nRead, checkIt;
  173.  
  174.     checkIt = 1;
  175.     if (gettingFile) {
  176.         if (gettingBinary) {                /* icky binary file */
  177.             /* printf("Whoa!  That's a binary file\n"); */
  178.             fd = open(tmpData, "r");
  179.             while ((nRead = read(fd, buf, sizeof buf)) > 0) {
  180.                 write(1, buf, nRead);
  181.             }
  182.             close(fd);
  183.         } else {                            /* must be a nice texty file */
  184.             fp = OpenOrDie(tmpData, "r");
  185.             while (fgets(buf, sizeof buf, fp) != NULL) {
  186.                 if (checkIt) { /* Just peek at it once */
  187.                     checkIt = 0;
  188.                     if (NotText(buf)) {
  189.                         fclose(fp);
  190.                         Abort("Sorry.  File does not appear to contain text.");
  191.                     }
  192.                 }
  193.                 buf[strlen(buf) - 1] = '\0';    /* munge LF */
  194.                 FailErr(printf("%s\r\n", buf));
  195.             }
  196.             fclose(fp);
  197.             FailErr(printf(".\r\n"));
  198.         }
  199.     } else {                        /* Must be a directory */
  200.         fp = OpenOrDie(tmpList, "r");
  201.         while (fgets(buf, sizeof buf, fp) != NULL) {
  202.             GopherType(buf, theName);
  203.             FailErr(printf("%s\t%s@%s%s\t%s\t%d\r\n", theName, host, thing,
  204.                     buf, myName, LOCALPORT));
  205.         }
  206.         fclose(fp);
  207.         FailErr(printf(".\r\n"));
  208.     }
  209. }
  210.  
  211. /*--------------------------------*/
  212.  
  213. FILE *OpenOrDie(file, mode)
  214.     char *file, *mode;
  215. {
  216.     FILE *fp, *fopen();
  217.     if ((fp = fopen(file, mode)) != NULL) {
  218.         return(fp);
  219.     } else {
  220.         Abort("Could not complete the transfer.");
  221.     }
  222. }
  223.  
  224. /*--------------------------------*/
  225. NotText(buf)
  226.     char * buf;
  227. {
  228.     int max;   char *c;
  229.     
  230.     if ((max = strlen(buf)) >= (BUFSIZ - 50)) max = BUFSIZ - 50;
  231.     for (c = buf; c < (buf + max); c++) {
  232.         if (*c > '~') return(1);
  233.     }
  234.     return(0);
  235. }
  236.  
  237. /*--------------------------------*/
  238.  
  239. Abort(complaint)
  240.     char *complaint;
  241.  
  242. {
  243.     printf("3 Error: %s\r\n.\r\n", complaint); 
  244.     Cleanup();
  245.     exit(1);
  246. }
  247.  
  248. /*--------------------------------*/
  249.  
  250. IsBinaryType(thing)
  251.     char *thing;
  252. {
  253.     static char *binExt[] = {
  254.         ".zip", ".zoo", ".arj", ".arc", ".lzh", ".hyp", ".pak", ".exe", ".com",
  255.         ".ps", ".gif", ".pict", ".pct", ".tiff", ".tif", ".tar", ".Z"
  256.     };
  257.  
  258.     int extType, i;
  259.     
  260.     for (extType = 0; extType < 17; extType++) { 
  261.         i = strcasecmp(thing + strlen(thing) - strlen(binExt[extType]),
  262.                          binExt[extType]);
  263.         if (i == 0) return(1);
  264.     }
  265.     return(0);
  266.  
  267. }
  268.  
  269. /*--------------------------------*/
  270.  
  271. GenerateUniqueFiles(tmpList, tmpData)
  272.     char *tmpList, *tmpData;
  273. {
  274.     char *s;
  275.     int pid;
  276.     
  277.     pid = getpid();
  278.     s = strchr(tmpList, '+');
  279.     sprintf(s, "%d", pid);
  280.     s = strchr(tmpData, '+');
  281.     sprintf(s, "%d", pid);
  282. }
  283.  
  284. /*--------------------------------*/
  285.  
  286. GopherType(buf, theName)
  287.     char *buf, *theName;
  288.  
  289. {
  290.     static char ext4[] = ".hqx";
  291.     static char *ext5[] = {".zip", ".zoo", ".arj", ".arc", ".lzh", ".hyp", 
  292.                         ".pak", ".exe", ".com", ".ps", ".gif", ".pict", 
  293.                         ".pct", ".tiff", ".tif"};
  294.     static char *ext9[] = {".tar", ".Z"};
  295.     int extType, i, last;
  296.     char    tmpName[SLEN];    
  297.     
  298.     last = strlen(buf) - 1;     buf[last--] = '\0';  /* Munge the LF */
  299.     strcpy(tmpName, buf);
  300.     if (buf[last] == '/') {
  301.         tmpName[last] = '\0';
  302.         sprintf(theName, "%d%s", GDIR, tmpName);
  303.         return;
  304.     }
  305.     if ((buf[last] == '*') || (buf[last] == '@')) {        /* Hack out * and @ */
  306.         buf[last] = '\0';
  307.         tmpName[last] = '\0';
  308.     }
  309.     
  310.     /* At this point we're looking at a file */
  311.     if (strcasecmp(buf + strlen(buf) - strlen(ext4), ext4) == 0) { /* BinHex? */
  312.         sprintf(theName, "%d%s", GBINHEX, tmpName);
  313.         return;
  314.     }
  315.  
  316.     for (extType = 0; extType < 15; extType++) {            /* PC garbage? */ 
  317.         i = strcasecmp(buf + strlen(buf) - strlen(ext5[extType]), 
  318.                         ext5[extType]);
  319.         if (i == 0) {
  320.             sprintf(theName, "%d%s", GDOSB, tmpName);
  321.             return;
  322.         }
  323.     }
  324.  
  325.     for (extType = 0; extType < 2; extType++) {                /* unix binary? */ 
  326.         i = strcasecmp(buf + strlen(buf) - strlen(ext9[extType]), 
  327.                         ext9[extType]);
  328.         if (i == 0) {
  329.             sprintf(theName, "%d%s", GUNIXB, tmpName);
  330.             return;
  331.         }
  332.     }
  333.     
  334.     sprintf(theName, "%d%s", GFILE, tmpName);
  335.     return;        /* Some other and hopefully text file */
  336. }
  337.  
  338. /*--------------------------------*/
  339.  
  340. Cleanup()
  341. {
  342.     unlink(tmpList);
  343.     unlink(tmpData);
  344.     exit(1);
  345. }
  346.  
  347. /*--------------------------------*/
  348.  
  349. RoundEmUp()
  350. {
  351.     
  352.     kill(childpid, SIGKILL);
  353.     Cleanup();
  354. }
  355.  
  356. /*--------------------------------*/
  357.  
  358. FailErr(result)
  359.     int result;
  360. {
  361.     if (result < 0) {
  362.         Cleanup();
  363.     }
  364. }
  365.  
  366. /*--------------------------------*/
  367.